let fmteraser_name = "fmteraser" in
let no_type_check = ref false in
let verbose = ref false in
let warn_errors = ref "" in
let warnings = ref "" in
let srcs = ref [] in
let spec =
  Arg.align [
    ("-no-type-check", Arg.Set no_type_check,
     " Do not type-check progam before translation");
    ("-where", Arg.Unit (fun () -> print_endline Autoconfig.libdir ; exit 0),
     " Print location of lazy-ocaml standard library and exit");
    ("-w", Arg.String (fun s -> warnings := !warnings ^ s),
     "warning-list Enable or disable warnings");
    ("-warn-error", Arg.String (fun s -> warn_errors := !warn_errors ^ s),
     "warning-list Turn warnings into errors");
    ("-verbose", Arg.Set verbose,
     " Verbose mode");
    ("-version", Arg.Unit (fun () -> print_endline Autoconfig.version ; exit 0),
     " Print version and exit");
  ]
in
let usage =
  Printf.sprintf "Usage: %s [ OPTIONS ] [ <src>.ml | <src>.mli ] ...\n"
    Sys.argv.(0)
in
let src_fmteraser = Filename.concat Autoconfig.bin fmteraser_name in
let inst_fmteraser = Filename.concat Autoconfig.bindir fmteraser_name in
let fmteraser =
  if Sys.file_exists src_fmteraser then src_fmteraser else inst_fmteraser
in
let error msg =
  Printf.printf "Error: %s\n" msg;
  Arg.usage spec usage;
  exit 1;
in
let unknow arg =
  if Filename.check_suffix arg ".ml" || Filename.check_suffix arg ".mli" then
    srcs := arg :: !srcs
  else
    error ("invalid option: " ^ arg)
in
let compile_ml src_file dst_file =
  let inputfile = Pparse.preprocess src_file in
  let output = open_out dst_file in
  let ast =
      Pparse.file Format.std_formatter inputfile Parse.implementation
	Config.ast_impl_magic_number
  in
  let ast_with_lazy_lib = {
    Parsetree.pstr_desc =
      Parsetree.Pstr_open (Longident.Lident "Pervasives");
    Parsetree.pstr_loc = Location.none } :: ast in
  let lazy_impl = Lazify.implementation ast_with_lazy_lib in
    Astpp.println output (Mldoc.doc_of_implementation lazy_impl);
    Pparse.remove_preprocessed inputfile;
    close_out output;
and compile_mli src_file dst_file =
  let inputfile = Pparse.preprocess src_file in
  let output = open_out dst_file in
  let ast =
    Pparse.file Format.std_formatter inputfile Parse.interface
      Config.ast_intf_magic_number
  in
  let ast_with_lazy_lib = {
    Parsetree.psig_desc =
      Parsetree.Psig_open (Longident.Lident "Pervasives");
    Parsetree.psig_loc = Location.none } :: ast in
  let lazy_interf = Lazify.interface ast_with_lazy_lib in
    Astpp.println output (Mldoc.doc_of_signature lazy_interf);
    Pparse.remove_preprocessed inputfile;
    close_out output;
in
let typecheck src_file =
  let warnings =
    if !warnings <> "" then "-w " ^ !warnings else ""
  in
  let warn_errors =
    if !warn_errors <> "" then "-warn-error " ^ !warn_errors else ""
  in
  let flags =
    if warnings = "" && warn_errors = "" then ""
    else if warnings = "" then warn_errors ^ " "
    else if warn_errors = "" then warnings ^ " "
    else warnings ^ " " ^ warn_errors ^ " "
  in
  let cmnd =
    Printf.sprintf "%s %s-i -pp %s %s > /dev/null"
      Autoconfig.ocamlc flags fmteraser src_file
  in
    if !verbose then Printf.printf "+ %s\n%!" cmnd;
    if Sys.command cmnd <> 0 then exit 1;
in
let compile src_file =
  if not !no_type_check then (
    if !verbose then Printf.printf "- typecheck %S\n%!" src_file;
    typecheck src_file;
  );
  let dst_file = "lazy_" ^ String.uncapitalize (Filename.basename src_file) in
    if !verbose then Printf.printf "- lazify %S -> %S\n%!" src_file dst_file;
    if Filename.check_suffix src_file ".ml" then compile_ml src_file dst_file
    else compile_mli src_file dst_file
in
  Arg.parse spec unknow usage;
  if !no_type_check && (!warnings <> "" || !warn_errors <> "") then
    error "incompatible options";
  srcs := List.rev !srcs;
  List.iter compile !srcs;
;;
